﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Downplay.Alchemy.Dynamic;
using ClaySharp;

namespace Downplay.Alchemy.Tests.Dynamics {


    [TestFixture]
    public class JsonTests {
        [Test]
        public void CanSerializeEmptyToJson() {
            dynamic stuff = new Stuff();
            string json = stuff.Json();
            Assert.That(json, Is.EqualTo("null"));
            stuff = new Stuff();
            stuff.Json("null");
            Assert.That(stuff.Supertype(), Is.EqualTo("Null"));
        }
        [Test]
        public void CanSerializeSinglePropertyToJson() {
            dynamic stuff = new Stuff();
            stuff.Foo = "Bar";
            Assert.That(stuff.Supertype(), Is.EqualTo("Object"));
            Assert.That(stuff.Foo.Supertype(), Is.EqualTo("Value"));
            Assert.That(stuff.Foo.Stereotype(), Is.EqualTo("String"));
            Assert.That(stuff["Foo"].Stereotype(), Is.EqualTo("String"));
            Assert.That(stuff.Foo=="Bar", Is.EqualTo(true));
            Assert.That(stuff.Foo.Get(), Is.EqualTo("Bar"));
            Assert.That((string)stuff.Foo, Is.EqualTo("Bar"));
            Assert.That(stuff.Foo.Get().ToString(), Is.EqualTo("Bar"));

            // Test getmembers
            var values = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
            var clay = stuff as IClayBehaviorProvider;
            clay.Behavior.GetMembers(() => null, clay, values);
            Assert.That(values.Count, Is.EqualTo(1));
            Assert.That(values["Foo"], Is.TypeOf<Stuff>());
            Assert.That(((dynamic)values["Foo"]).Get(),Is.TypeOf<String>());
            string json = stuff.Json();
            Assert.That(json, Is.EqualTo("{\"Foo\":\"Bar\"}"));
        }
        [Test]
        public void CanSerializeArrayToJson() {
            dynamic stuff = new Stuff(new object[] { "Foo", 1, "Bar", 23 });
            Assert.That((string)stuff.Json(), Is.EqualTo("[\"Foo\",1,\"Bar\",23]"));
        }
        [Test]
        public void CanDeserializeSinglePropertyFromJson() {
            dynamic stuff = new Stuff();
            stuff.Json("{\"Foo\":\"Bar\"}");
            Assert.That((string)stuff.Foo, Is.EqualTo("Bar"));
        }

        [Test]
        public void CanSerializeComplexObjectToJson() {
            dynamic stuff = new Stuff(new {
                Foo= "Bar",
                Zoo= new[]{ "Cat","Bat","Rat" },
                Hats= new {
                    Wide= new Hat(){ Width= 100,Depth= 50 },
                    Tall= new Hat(){ Width= 50, Depth= 100} 
                }
            });
            stuff.Hats.Wide.Style = "Polka";
            string json = stuff.Json();
            Assert.That(json, Is.EqualTo("{\"Foo\":\"Bar\",\"Zoo\":[\"Cat\",\"Bat\",\"Rat\"],\"Hats\":{\"Wide\":{\"Width\":100,\"Depth\":50,\"Style\":\"Polka\"},\"Tall\":{\"Width\":50,\"Depth\":100}}}"));
        }

        public class Hat {
            public int Width { get; set; }
            public int Depth { get; set; }
        }

        [Test]
        public void CanDeserializeComplexPropertiesFromJson() {
            dynamic stuff = new Stuff();
            stuff.Json("{\"Foo\":{\"One\":1,\"Two\":[1,2]}}");
            Assert.That(stuff.Json(), Is.EqualTo("{\"Foo\":{\"One\":1,\"Two\":[1,2]}}"));
            Assert.That(stuff.Foo.Supertype(), Is.EqualTo("Object"));
            Assert.That((int)stuff.Foo.One,Is.EqualTo(1));
            Assert.That((string)stuff.Foo.Two.Supertype() ,Is.EqualTo("Array"));
            Assert.That(stuff.Foo.Two.Count(),Is.EqualTo(2));
        }

    }
}
